<?php
declare(strict_types=1);

/**
 * 后台首页
 */

namespace app\admin\controller;

use app\common\service\admin\MenuService;
use app\common\model\Admin as AdminModel;
use app\common\model\AuthGroup as AuthGroupModel;
use app\common\model\LoginLog as LoginLogModel;
use think\facade\Cache;
use think\facade\View;
use think\facade\Db;
use libs\IpToAddress;
use think\Response;
use app\common\service\admin\CacheClearService;

class Index extends Base
{

    /**
     * 首页
     * @return string
     */
    public function index(): string
    {
        //获取后台已登录的管理员id
        $adminId = cmf_get_admin_id();
        View::assign('admin_id', $adminId);

        return View::fetch();
    }

    /**
     * 后台菜单json 该方法用于public/static/admin/lib/pear/pear.config.yml
     * @return void
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function menuJson(): void
    {
        $adminId = cmf_get_admin_id();

        // 检查用户ID是否存在
        if (empty($adminId)) {
            $this->error('用户未登录');
        }

        //获取缓存数据，使用用户ID作为缓存键的一部分
        $cacheData = Cache::get('initAdmin_'.$adminId);

        if ( ! empty($cacheData)) {
            $this->success('获取成功', $cacheData);
        }

        $menuService = new MenuService($adminId);

        //获取后台菜单树信息
        $data = $menuService->getMenuTree();

        //给缓存initAdmin打个标记，使用用户ID作为缓存键的一部分
        Cache::tag('initAdmin_'.$adminId)->set('initAdmin_'.$adminId, $data);
        $this->success("获取成功", $data);
    }

    /**
     * 后台欢迎页 该方法用于public/static/admin/lib/pear/pear.config.yml
     * @return string
     */
    public function welcome(): string
    {
        $adminId                 = cmf_get_admin_id();
        $roleIdArr               = AuthGroupModel::getAdminGroupNamesById($adminId);
        $adminInfo               = AdminModel::find($adminId);
        $adminInfo['group_name'] = implode(',', $roleIdArr);

        $this->assign('admin_info', $adminInfo);
        $this->assign('sys_info', $this->getSysInfo());

        return View::fetch("welcome");
    }

    /**
     * 后台清理缓存 该方法用于app/admin/view/index/index.html
     * @return void
     */
    public function clearCache(): void
    {
        $adminId = cmf_get_admin_id();
        CacheClearService::cacheClearThis($adminId);
        $this->success('清理缓存成功');
    }

    /**
     * 输出后台账户信息
     * @return void
     */
    public function accountInfo(): void
    {
        $adminInfo = cmf_get_current_admin_info();
        $adminId   = cmf_get_admin_id();

        $returnArr = [
            'id'       => $adminId,
            'username' => $adminInfo['username'] ?? "",
            'nickname' => $adminInfo['nickname'] ?? "",
            'login_ip' => $adminInfo['loginip'] ?? ""
        ];

        // 判断是否开启后台登陆日志：
        if (get_config("login_log_admin")) {
            $this->fillAccountInfoWithLoginLog($returnArr, $adminId, $adminInfo);
        } else {
            $this->fillAccountInfoWithoutLoginLog($returnArr, $adminInfo);
        }

        $this->success("ok", $returnArr);
    }

    /**
     * 填充带登录日志的账户信息
     *
     * @param array $returnArr
     * @param int   $adminId
     * @param array $adminInfo
     *
     * @return void
     */
    private function fillAccountInfoWithLoginLog(array &$returnArr, int $adminId, array $adminInfo): void
    {
        // 获取最新的2条登陆日志
        $loginLogs = LoginLogModel::where(['user_id' => $adminId])->order("id desc")->limit(2)->select()->toArray();

        // 处理当前登录信息
        $currentLogin               = $loginLogs[0] ?? [];
        $isp0                       = $currentLogin['isp'] ?? "";
        $country0                   = $currentLogin['country'] ?? "";
        $area0                      = $currentLogin['area'] ?? "";
        $city0                      = $currentLogin['city'] ?? "";
        $returnArr['login_address'] = trim("{$isp0} {$country0} {$area0} {$city0}");

        // 处理上次登录信息
        $lastLogin = $loginLogs[1] ?? [];
        $isp1      = $lastLogin['isp'] ?? "";
        $country1  = $lastLogin['country'] ?? "";
        $area1     = $lastLogin['area'] ?? "";
        $city1     = $lastLogin['city'] ?? "";

        $returnArr['last_login_time']    = $lastLogin['create_time'] ?? "";
        $returnArr['last_login_ip']      = $lastLogin['ip_address'] ?? "";
        $returnArr['last_login_address'] = trim("{$isp1} {$country1} {$area1} {$city1}");
    }

    /**
     * 填充不带登录日志的账户信息
     *
     * @param array $returnArr
     * @param array $adminInfo
     *
     * @return void
     */
    private function fillAccountInfoWithoutLoginLog(array &$returnArr, array $adminInfo): void
    {
        $ipToAdd = new IpToAddress();
        $res     = $ipToAdd->ipToAddress($adminInfo['loginip']);
        $country = $res['country'] ?? "";
        $area    = $res['province'] ?? "";
        $city    = $res['city'] ?? "";
        $isp     = $res['isp'] ?? "";

        $returnArr['login_address']      = trim("{$isp}{$country} {$area} {$city} ");
        $returnArr['last_login_time']    = "";
        $returnArr['last_login_ip']      = "";
        $returnArr['last_login_address'] = "";
    }

    /**
     * phpinfo信息 按需显示在前台
     * @return array
     */
    private function getSysInfo(): array
    {
        $sysUploadMaxFilesize = (int)convert_size_to_kb(ini_get('upload_max_filesize'));
        $phpUploadMaxFilesize = (int)(get_config('upload_maxsize'));
        $maxFileSize          = max($sysUploadMaxFilesize, $phpUploadMaxFilesize) * 1000;

        $sysInfo = [
            'os'              => PHP_OS, //操作系统
            'web_server'      => $_SERVER['SERVER_SOFTWARE'] ?? '', //服务器环境
            'phpv'            => phpversion(), //php版本
            'fileupload'      => @ini_get('file_uploads') ? sizecount($maxFileSize) : 'unknown', //文件上传限制
            'memory_limit'    => ini_get('memory_limit'), //最大占用内存
            'domain'          => request()->host(), //域名
            'remaining_space' => round((@disk_free_space(".") / (1024 * 1024)), 2).'M', //剩余空间
            'beijing_time'    => gmdate("Y年n月j日 H:i:s", time() + 8 * 3600), //北京时间
            'time'            => date("Y年n月j日 H:i:s"), //服务器时间
        ];

        // MySQL版本
        try {
            $mysqlinfo                = Db::query("SELECT VERSION() as version");
            $sysInfo['mysql_version'] = $mysqlinfo[0]['version'] ?? 'unknown';
        } catch (\Exception $e) {
            $sysInfo['mysql_version'] = 'unknown';
        }

        // GD库版本
        if (function_exists("gd_info")) {
            $gd                = gd_info();
            $sysInfo['gdinfo'] = $gd['GD Version'] ?? 'unknown';
        } else {
            $sysInfo['gdinfo'] = "未知";
        }

        // ImageMagick 信息
        $imageMagickInfo                 = $this->getImageMagickInfo();
        $sysInfo['image_magick']         = $imageMagickInfo['status'];
        $sysInfo['image_magick_version'] = $imageMagickInfo['version'];

        return $sysInfo;
    }

    /**
     * 获取 ImageMagick 信息
     * @return array
     */
    private function getImageMagickInfo(): array
    {
        // 首先检查是否启用了 imagick 扩展
        if (extension_loaded('imagick')) {
            try {
                $imagick = new \Imagick();
                $version = $imagick->getVersion();

                return [
                    'status'  => '扩展可用',
                    'version' => $version['versionString'] ?? '未知版本'
                ];
            } catch (\Exception $e) {
                return [
                    'status'  => '扩展加载但不可用',
                    'version' => '未知'
                ];
            }
        }

        // 检查是否可以通过 exec 执行 convert 命令
        if (function_exists('exec')) {
            try {
                // Windows 系统检查 magick 命令，其他系统检查 convert 命令
                $isWindows = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
                $command   = $isWindows ? 'magick --version' : 'convert --version';
                exec($command.' 2>&1', $output, $returnCode);

                if ($returnCode === 0 && ! empty($output)) {
                    // 提取版本信息
                    $versionInfo = implode(' ', array_slice($output, 0, 2)); // 取前两行

                    return [
                        'status'  => '命令行可用',
                        'version' => $versionInfo
                    ];
                }
            } catch (\Exception $e) {
                // 继续检查其他可能性
            }
        }

        return [
            'status'  => '不可用',
            'version' => '未知'
        ];
    }

}
